#ifndef RAY_TRACE_PRO_DEBUG_H
#define RAY_TRACE_PRO_DEBUG_H

#include <Windows.h>
#include <stdio.h>
#include <hash_map>

namespace RayTracePro
{
	class DebugTimming
	{
	private:
		struct CounterItem
		{
			LARGE_INTEGER start;
			float time;
			const char * name;
			CounterItem * parent;
			int level;
			CounterItem()
			{
				time = 0.0f;
				start.QuadPart = 0;
				name = 0;
				parent = 0;
				level = 0;
			}
			CounterItem(const char* name, CounterItem * parent)
			{
				this->name = name;
				this->parent = parent;
				if (parent)
					this->level = parent->level + 1;
				else
					this->level = 0;
				start.QuadPart = 0;
				time = 0.0f;
			}
			void Print(LARGE_INTEGER freq)
			{
				float parentTime = time;
				if (parent)
					parentTime = parent->time;
				for (int i = 0; i<level; i++)
					printf("  ");
				printf("%s... %.3fs (%.1f%%)\n", name, time, time/parentTime*100.0f); 
			}
		};
		LARGE_INTEGER freq;
		std::hash_map<const char*, CounterItem> counters;
		const char* counterStack[32];
		const char * counterList[32];
		int parentPtr, counterPtr;
		void Print()
		{
			for (int i = 0; i<counterPtr; i++)
				counters[counterList[i]].Print(freq);
		}
		void Clear()
		{
			parentPtr = counterPtr = 0;
			counters.clear();
		}
	public:
		DebugTimming()
		{
			QueryPerformanceFrequency(&freq);
			parentPtr = 0;
			counterPtr = 0;
		}
		inline void Start(const char * str)
		{
			CounterItem counter;
			std::hash_map<const char*, CounterItem>::iterator citer;
			if ((citer=counters.find(str)) != counters.end())
				counter = citer->second;
			else
				counterList[counterPtr++] = str;
			counter.name = str;
			if (parentPtr != 0)
			{
				counter.parent = &counters[counterStack[parentPtr-1]];
				counter.level = counter.parent->level + 1;
			}
			else
			{
				counter.parent = 0;
				counter.level = 0;
			}
			QueryPerformanceCounter(&counter.start);
			counters[str] = counter;
			counterStack[parentPtr++] = str;
			
		}

		inline void End()
		{
			if (parentPtr)
			{
				parentPtr--;
				const char* name = counterStack[parentPtr];
				LARGE_INTEGER end;
				QueryPerformanceCounter(&end);
				CounterItem &counter = counters[name];
				counter.time += (end.QuadPart-counter.start.QuadPart)/(float)freq.QuadPart;
				if (parentPtr == 0)
				{
					Print();
					Clear();
				}
			}
		}
		
	};
}

#endif